home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / oper_sys / emerald / emrldsys.lha / Kernel / Em / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-08-17  |  22.3 KB  |  888 lines

  1.  
  2. /* File: /usr/em/Kernel/Em/main.c July 8th, 1985 Emerald kernel main.c */
  3.  
  4. /*
  5.  * $Header$
  6.  *
  7.  * em [ -N lnn ] [ -x debug_level ] [ -t trace_level ] \
  8.  *            [ -d dimension ] [ -k configurefile ]
  9.  *
  10.  * This module is designed to be used as the main loop for Eden kernel.
  11.  *
  12.  * Higher debug levels give more information.  For now the debug info
  13.  * comes out on the error output.  This needs to be changed.
  14.  * There is also a Prod facility which may be used to get a stalled
  15.  * kernel process to print out a little bit of data concerning it's state.
  16.  * This state information only concerns signal handling.
  17.  *
  18.  * The dimension parameter will put the host/pod into the specified
  19.  * dimension, default is 0.  For testing separate Eden systems only.
  20.  * Not intended for use other than Message Module testing.
  21.  *
  22.  * This is really a kind of multi-tasking exec.  Tasks can specify
  23.  * handlers for various events.  They can then queue the event, or let
  24.  * a Unix signal queue the event.  The main loop just checks the queue
  25.  * for unhandled events and calls the handler.  This insures that the
  26.  * handlers will be called in the same order in which the events occured.
  27.  *
  28.  * The configure file parameter may be used to change the name of the
  29.  * default configure file searched for.
  30.  * It contains pairs of name and new value for integers.  Note that
  31.  * the setting of these values happen early - before initialization routines
  32.  * are called. -- Eric Jul, 1984-05-16.
  33.  *
  34.  * TaskQ is a queue holding events that need to be handled.  Events
  35.  * are put on by RealSigHandler as a result of a signal.  They are taken
  36.  * off by the main loop as each one is handled.
  37.  *
  38.  * FreeQ is the free list.
  39.  *
  40.  * The interpreter is built into the mainLoop of the kernel:
  41.  * The mainLoop is in a separate source file.
  42.  *
  43.  *
  44.  * 10 Nov 82    Originally written by Jim Rees
  45.  * 15 Dec 83    Major rewrite for one process kernel by J. Sanislo
  46.  * 06 Jul 84    Changes made to switch from use of Unix 4.1 to 4.2 signals
  47.  * 01 Aug 84    Split out MainLoop procedure into a separate file.
  48.  * 08 Jul 85    Initial modification to become an Emerald kernel.
  49.  */
  50. char *nodeKind =
  51.     "Emerald Node";
  52.  
  53. #define ROOTDIR "/scratch/eric/emerald/"
  54.  
  55. #ifdef RCSID
  56. static char rcsid[] = "$Header$";
  57. #endif
  58. #include <stdio.h>
  59. #include <signal.h>
  60. #include <pwd.h>
  61. #include <sys/types.h>
  62. #include <sys/stat.h>
  63. #ifdef xkernel
  64. #include "userupi.h"
  65. #include "userprocess.h"
  66. #else
  67. #include <netdb.h>
  68. #endif
  69.  
  70. #include "Kernel/h/assert.h"
  71.  
  72. #undef integer        /* Silly stdtypes */
  73. #include "Kernel/h/system.h"
  74. #include "Kernel/h/stdTypes.h"
  75. #include "Kernel/h/mmCodes.h"
  76. #include "Kernel/h/mmTypes.h"
  77. #include "Kernel/h/mmMsgDefs.h"
  78. #include "Kernel/h/mmMsgTypes.h"
  79. #include "Kernel/h/kBootCodes.h"
  80. #include "Kernel/h/kEvents.h"
  81. #include "Kernel/h/hotsTypes.h"
  82. #include "Kernel/h/kmdDefs.h"
  83. #include "Kernel/h/kmdTypes.h"
  84. #include "Kernel/h/emPorts.h"
  85. #include <errno.h>
  86. #include "Kernel/h/ecTypes.h"
  87. #include "Kernel/h/emTypes.h"
  88.  
  89. #define EMKERNELVERSION "Version 10.00"
  90. #define EMKERNELVERSIONDATE " @(#)main.c    1.9 2/23/90"
  91.  
  92. extern int *VarLookup();
  93. /* extern int *sprintf(); Removed because stdio.h does it */
  94.  
  95. #define SIGPROD         31
  96. #define SIGDBXPROD      30
  97. #define CONFFILE        "emrc"
  98.  
  99. /*
  100.  * The following are `constant' strings defined at
  101.  * node start up time.
  102.  */
  103. char EMDIR[100];        /* Home directory for user USERNAME,
  104.                    e.g. "/usr/em/" */
  105.  
  106. char progArg0Name[100];         /* Name of kernel program. */
  107.  
  108. extern char vMMEtherDevName[];
  109.  
  110. #ifndef NODISK
  111. char NODEDIR[100];        /* Node directory,
  112.                     e.g. "/usr/em/Nodes/HN0001/"  */
  113. char nodisk;            /* diskless kernel can be had at compile time
  114.                  * with -DNODISK or runtime with nodisk!=0
  115.                  */
  116. #endif
  117.  
  118. time_t  nodeIncarnationId;      /* IncarnationId: use ctime(3) */
  119. time_t  cEmVersion = EMVERSION; /* Software version control (ctime(3)) */
  120.  
  121. /* "forward" */
  122. extern void MainLoop();
  123. extern void shutdownOID();
  124. extern void SetLNN();
  125.  
  126. extern void FLInit(), EmInit(), ItemInit();
  127.  
  128. extern EmBadSignal();
  129. int emPlane = 0;
  130. int emPort = EMKERNELDEFAULTPORTNUMBER;
  131.  
  132. /*
  133.  * Routines to initialize main data structures.
  134.  */
  135.  
  136. char myHostName[100];
  137. FILE *logout;                   /* fp for log file  */
  138. int IamPOD;                     /* obsolete and should go. */
  139. NodeNum defaultCS;        /* Default checksite for created ejects */
  140. int onlyFindingOIDs = 0;
  141.  
  142. /*
  143.  * Define auxilliary signal stack.
  144.  * The purpose of this stack is to avoid having ULTRIX signal handlers
  145.  * running on Emerald process stacks.
  146.  */
  147.  
  148. #define SIGSTACKSIZE 10000 /* integers */
  149.  
  150. long signalstack[SIGSTACKSIZE];
  151.  
  152. /* Table of physical machine string names and ethernet addresses */
  153. #ifdef WASHINGTON
  154. #define NUMEMMACHINES 12
  155. char *EmMachineNames[NUMEMMACHINES] = 
  156.     {
  157.      "whistler", "skagit", "bezier", "taber", "larry",
  158.      "june", "krakatoa", "roskilde", "tahiti", "beaver",
  159.      "wally", "crystal"
  160.     };
  161. #endif
  162. #ifdef ARIZONA
  163. #define NUMEMMACHINES 5
  164. char *EmMachineNames[NUMEMMACHINES] = 
  165.     {
  166.      "megaron", "arizona", "bocklin", "lectura",
  167.      "jenson"
  168.     };
  169. #endif
  170. #ifdef DIKU
  171. #define NUMEMMACHINES 5
  172. char *EmMachineNames[NUMEMMACHINES] = 
  173.     {
  174.      "diku", "thor", "roar", "bjarke", "regnar"
  175.     };
  176. #endif
  177.  
  178. EtherNetAddress EmMachineAddrs[NUMEMMACHINES], myEtherAddr;
  179. int NumEmMachines = NUMEMMACHINES;
  180.  
  181. int SigIntHandler();
  182. int ProdHandler();
  183. int DBXProdHandler();
  184.  
  185. checkEnvironment()
  186. {
  187.   char *emplanename;
  188.   extern char *getenv();
  189.  
  190.   emplanename = getenv("EMPLANE");
  191.   if (emplanename != NULL) {
  192.     emPlane = atoi(emplanename);
  193.     if (emPlane < 0 || emPlane > 100) {
  194.       printf("Invalid EMPLANE %s\n", emplanename);
  195.       exit(1);
  196.     }
  197.   }
  198. }
  199.  
  200. void
  201. computeEmPort()
  202. {
  203.   struct servent   *myService;
  204. #ifdef DIKU
  205.   myService = getservbyname(EMKERNELSERVICEPORT, "tcp");
  206.   if(myService)
  207.     emPort = ntohs(myService->s_port);
  208. #endif
  209.   emPort += emPlane*4;
  210. }
  211.  
  212. /*
  213.  *
  214.  * SetFlush
  215.  *
  216.  * Snapshot to turn flushing of stdout on/off.
  217.  *
  218.  */
  219. /* Snapshot */
  220. void SetFlush(fInt, fString)
  221. int             fInt;
  222. char           *fString;
  223. {
  224.     if(!strcmp(fString, "on")) {
  225.     setlinebuf(stdout);
  226.     KMDPrint("Flushing turned on.\n");
  227.     } else
  228.     if(!strcmp(fString, "off")) {
  229.     setbuf(stdout,NULL);
  230.     KMDPrint("Flushing turned off.\n");
  231.     } else {
  232.     KMDPrint("Option %s not understood.");
  233.     }
  234. }
  235.  
  236.  
  237. /*
  238.  * This is it!  The main program of the Emerald kernel process.
  239.  */
  240.  
  241. #ifdef xsun3
  242. kbd_demux()
  243. {
  244.   xkhandlerstart();
  245.   xkhandlerend();
  246. }
  247.  
  248. kbd_other()
  249. {
  250.   xkhandlerstart();
  251.   xkhandlerend();
  252. }
  253.  
  254. initKeyboard()
  255. {
  256.   static struct {
  257.     char *addr;
  258.     int len;
  259.   } whom = { 0 , 0 };
  260.   int foo;
  261.   SESSN bar;
  262.   foo = xcreateprotl(kbd_demux, kbd_other, kbd_other);
  263.   if (foo < 0) 
  264.     printf("main: xcreateprotl failed\n");
  265.   bar = xopen(foo, KBD, whom);
  266.   if (bar < 0) {
  267.     printf("main: xopen KBD failed\n");
  268.   } else {
  269.     printf("main: xopen KBD worked\n");
  270.   }
  271. }
  272. #endif
  273.  
  274. #ifndef xkernel
  275. main(ac,av)
  276. int ac;
  277. char *av[];
  278. #else
  279. user(ac,av)
  280. int ac;
  281. char *av[];
  282. #endif
  283. {
  284.     int i, traceLevel = 3;
  285.     int Dimension =0;       /* which Ethernet dimension used. */
  286.     KKStatus lStatus;
  287.     extern void GCInit();
  288. #ifndef xkernel
  289.     struct sigvec vec;    /* used in sigvec() calls */
  290.     struct sigstack theStackInfo;
  291.     /* Variable for Search for full argv[0] pathname. */
  292.     char pathstring[100], *chp, *pathptr, confBuf[140];
  293. #define STBUFHASBEENDECLARED
  294.     struct stat stbuf;
  295.     int found = 0;
  296.     FILE *cfp;                       /* Configure parameter file. */
  297. #endif
  298.     Boolean nodeNumSeen = FALSE;
  299.     char *confFileName;
  300.     int argc;
  301.     Boolean standAlone = FALSE;
  302. #ifndef STBUFHASBEENDECLARED
  303. #ifndef NODISK
  304.     FILE *cfp;
  305.     struct stat stbuf;
  306.     char confBuf[140];
  307. #endif NODISK
  308. #endif STBUFHASBEENDECLARED
  309.     /*
  310.      * DataBrand is defined in ecTypes.h and used in kstub.4s
  311.          * If you change the value of DataBrand, do it in both those places
  312.      * and here too.
  313.      */
  314.     
  315.         assert(0 == (int) DataBrand);
  316.  
  317. #ifndef NOFLUSHSTDOUT
  318.     setbuf(stdout,NULL);
  319. #endif /* NOFLUSHSTDOUT */
  320.  
  321.     GCInit();
  322. #ifdef xkernel
  323.     initXK();
  324. #endif
  325.  
  326.     checkEnvironment();
  327.     computeEmPort();
  328.     /* Fill in Em machine string name / ethernet address table */
  329.     for (i = 0; i < NumEmMachines; i++) {
  330.         if(!mSUCCESS(
  331.         mMakeEtherNetAddr(EmMachineNames[i],
  332.                   EMKERNELSERVICEPORT, emPort,
  333.                   &(EmMachineAddrs[i]) )) )
  334.         {
  335.         bzero((char *) &EmMachineAddrs[i], sizeof(EmMachineAddrs[i]));
  336.         }
  337.     }
  338.  
  339.     /*
  340.      * Set file protection mask.
  341.      */
  342. #if defined(BSD) || defined (xsimul)
  343.     (void) umask(0);         /* rwx for everybody */
  344. #endif
  345. #ifdef OLDEDEN
  346.     /* Find the home directory for user Em */
  347.     if ((edenpw = getpwnam(USERNAME)) == NULL) {
  348.         ErrMsg("No user account for '%s' on this machine\n", USERNAME);
  349.         exit(1);
  350.     }
  351.     (void) strcpy(EMDIR, edenpw->pw_dir);
  352.     (void) strcat(EMDIR,"/");
  353. #else OLDEDEN
  354.     (void) strcpy(EMDIR, ROOTDIR);
  355. #endif OLDEDEN
  356.  
  357.     /*
  358.      * Find full path name of argv[0] file.
  359.      */
  360. #ifdef xkernel
  361.     strcpy(progArg0Name, av[0]);
  362. #else
  363.     (void) strcpy(progArg0Name, av[0]);
  364.     if ( (av[0][0] == '.') || (av[0][0] == '/') ) {
  365.         /* av[0] name ok. */
  366.         found++;
  367.     }
  368.     else {
  369.         /* Search through PATH to find full path name. */
  370.         pathptr = getenv("PATH");
  371.         do {
  372.         chp = pathstring;
  373.         while( (*pathptr != ':') && (*pathptr != '\0') ) {
  374.             *chp++ = *pathptr++;
  375.         }
  376.         *chp++ = '/'; *chp = '\0';
  377.         (void) strcat(pathstring,av[0]);
  378.         if ( !stat(pathstring,&stbuf) ) {
  379.             found++;
  380.             break;
  381.         }
  382.         if ( *pathptr == ':' ) pathptr++;
  383.         } while( *pathptr != '\0' );
  384.  
  385.         if ( found ) (void) strcpy(progArg0Name, pathstring);
  386.     }
  387. #endif
  388.  
  389.     /*
  390.      * Configuration file:  Before doing anything really try finding
  391.      * and reading in a configuration file.
  392.      * We scan the options TWICE.
  393.      */
  394.  
  395.     argc = ac;
  396.     confFileName = CONFFILE;
  397.  
  398.     while (ac > 1) {
  399.         if (av[1][0] == '-') switch (av[1][1]) {
  400. #ifndef NODISK
  401.         case 'k':               /* Set configuration file name. */
  402.             confFileName = av[2];
  403.             ac--; av++;    /* Skip over actual name. */
  404.             break;
  405. #endif
  406.         case 'E':
  407.             (void) strcpy(EMDIR, av[2]);
  408.             ac--; av++;     /* Skip over actual name */
  409.             break;
  410.             
  411.         }
  412.         ac--;
  413.         av++;
  414.     }
  415.     av -= (argc - ac); ac = argc;  /* Restore option ptr. for 2nd pass. */
  416.  
  417. #ifndef NODISK
  418.     if(!nodisk) {
  419.       if ( (cfp = fopen(confFileName, "r")) == (FILE *) NULL ) {
  420.         /* No user configure file - find system. */
  421.         (void) strcpy(confBuf, EMDIR);
  422.         (void) strcat(confBuf, CONFFILE);
  423.         confFileName = confBuf;
  424.         cfp = fopen(confFileName, "r");
  425.       }
  426.  
  427.     if ( cfp != NULL ) {       /* Found a configure file.     */
  428.         /* Now go thru it and read stuff out of it.           */
  429.         /* Rehacked Sept. 1988 so that strings can            */
  430.         /* be used too.                    */
  431.         char varName[140], someString[140];
  432.         int  varValue, *varAddr;
  433.         
  434.         printf("  Configure file: %s\n", confFileName);
  435.  
  436.         (void) fscanf(cfp, "#%*[^\n]%*c"); /* Skip rest of line. */
  437.  
  438.         while (fscanf(cfp, "%139s %139s", varName, someString) != EOF) {
  439.  
  440.         (void) fscanf(cfp, "%*[^\n]%*c"); /* Skip rest of line. */
  441.         
  442.         if ( varName[0] == '#' ) continue; /* Skip comment. */
  443.  
  444.         if ( someString[0] == '"' ) {
  445.             int length;
  446.             length     = strlen(someString);
  447.             if (length > 0) length--; /* Null out end-quote */
  448.             someString[length] = '\0';
  449.  
  450.             /* Lookup variable name and set value. */
  451.             if ((varAddr = VarLookup(varName)) == (int *) -1) {
  452.             ErrMsg(">> Configure var %s not found - ignored\n",
  453.                 varName);
  454.             continue;
  455.             };
  456.             printf("  var %s (0x%08x) = \"%s\"\n", varName, varAddr,
  457.             &someString[1]);
  458.             strcpy(varAddr, &someString[1]);/* Actually assign it. */
  459.             continue;
  460.         }
  461.         
  462.         /* Lookup variable name and set value. */
  463.         if (sscanf(someString, "%d", &varValue) != 1) {
  464.             ErrMsg(">> Configure var %s assigned bad value %s\n",
  465.             varName, someString);
  466.         }
  467.         
  468.         if ((varAddr = VarLookup(varName)) == (int *) -1) {
  469.             ErrMsg(">> Configure var %s not found - ignored\n",
  470.             varName);
  471.             continue;
  472.         };
  473.         printf("  var %s (0x%08x) = %d\n", varName, varAddr,
  474.             varValue);
  475.         *varAddr = varValue;        /* Actually assign it. */
  476.         };
  477.         (void) fclose(cfp);
  478.     };
  479.  
  480. #endif NODISK
  481.     /*
  482.      * Parse command line options
  483.      */
  484.     while (ac > 1 && av[1][0] == '-') {
  485.         switch (av[1][1]) {
  486.         case 'N':        /* Set logical node number */
  487.             if ( nodeNumSeen ) {
  488.                 ErrMsg(">>> Node number multiply defined.\n");
  489.                 exit(0);
  490.             }
  491.             if (av[1][2] == '\0') {
  492.                 i = atoi(av[2]);
  493.                 ac--;
  494.                 av++;
  495.             } else
  496.                 i = atoi(&av[1][2]);
  497.             SetLNN( i );
  498.             nodeNumSeen = TRUE;
  499.             break;
  500.         case 'k': /* Configure file name: skip it. */
  501.             ac--; av++;
  502.             break;
  503.         case 'E': /* Directory for kernel to use and find builtins */
  504.             /* Emerald dir name: skip it. */
  505.             ac--; av++;
  506.             break;
  507.         case 's': /* Stand alone mode: no HOTS stuff nor
  508.                Ethernet */
  509.             standAlone = TRUE;
  510.             break;
  511.         case 'x': /* debugmsg tracing to stdout */
  512.             if (av[1][2] == '\0') {
  513.                 DebugLevel = atoi(av[2]);
  514.                 ac--;
  515.                 av++;
  516.             } else
  517.                 DebugLevel = atoi(&av[1][2]);
  518.             break;
  519.         case 'l': /* trace level for -T and -S */
  520.             if (av[1][2] == '\0') {
  521.                 traceLevel = atoi(av[2]);
  522.                 ac--;
  523.                 av++;
  524.             } else
  525.                 traceLevel = atoi(&av[1][2]);
  526.             break;
  527.         case 'T':               /* Set a trace to stdout */
  528.         case 'S':               /* Set a trace to stdout */
  529.             if (av[1][2] == '\0') {
  530.                 KMDPrepareTrace(av[2], traceLevel);
  531.                 ac--;
  532.                 av++;
  533.             } else
  534.                 KMDPrepareTrace(&av[1][2], traceLevel);
  535.             break;
  536.         case 'j':               /* Define name of ethernet device */
  537.             if (av[1][2] == '\0') {
  538.                 (void) strcpy(&vMMEtherDevName[0], av[2]);
  539.                 KMDPrepareTrace(av[2], traceLevel);
  540.                 ac--;
  541.                 av++;
  542.             } else
  543.                 (void) strcpy(&vMMEtherDevName[0], &av[1][2]);
  544.             break;
  545.         case 't': /* MM tracing */
  546.             if (av[1][2] == '\0') {
  547.                 MMTrace = atoi(av[2]);
  548.                 ac--;
  549.                 av++;
  550.             } else
  551.                 MMTrace = atoi(&av[1][2]);
  552.             break;
  553.  
  554.         case 'o': /* Only find the OIDs in the checkpoint files */
  555.             onlyFindingOIDs = 1;
  556.             break;
  557.  
  558.         case 'd': /* Dimension  */
  559.             if (av[1][2] == '\0') {
  560.                 Dimension = atoi(av[2]);
  561.                 ac--;
  562.                 av++;
  563.             } else
  564.                 Dimension = atoi(&av[1][2]);
  565.             break;
  566.         }
  567.         ac--;
  568.         av++;
  569.     }
  570.     
  571.     if (gethostname( myHostName, sizeof(myHostName) ) == -1) {
  572. #ifdef BSD
  573.         fflush(stdout);  fflush(stderr);
  574. #endif
  575.         perror("gethostname");
  576.         abort();
  577.     }
  578.  
  579.       DebugMsg(2, "Using port %d\n", emPort);
  580.     
  581.     if (!nodeNumSeen) {
  582.         if (!mSUCCESS(mMakeEtherNetAddr(myHostName, EMKERNELSERVICEPORT,
  583.         emPort, &myEtherAddr)))
  584.         {
  585.         ErrMsg("Could not generate node number\n");
  586.         abort();
  587.         }
  588.         
  589.         SetLNN(MachineAddress(*(struct in_addr *)&myEtherAddr));
  590.     }
  591.     (void) sprintf( MMTraceHost, "Em%02x", GetLNN());
  592.  
  593. #ifdef xsun3
  594.     initKeyboard();
  595. #endif
  596.  
  597.     /* Turn on TRACING here */
  598.     KMDTest = 0;
  599.     i = nodeIncarnationId = time((time_t *) 0);
  600.     printf("\n  Emerald kernel  : %s of %s\n", EMKERNELVERSION,
  601.         EMKERNELVERSIONDATE);
  602.     printf("  Emerald version : %s", ctime(&cEmVersion));
  603.     printf("  Starting on     : %s", ctime((time_t *)&i) );
  604.     printf("  Physical node   : %s\n", myHostName);
  605.     printf("  Logical node    : %d (0x%02x) \n", GetLNN(), GetLNN());
  606.     printf("  Emplane         : %d (0x%02x) \n", emPlane, emPlane);
  607.     printf("  Kernel loadfile : %s\n", progArg0Name);
  608.     printf("  Debug Level     : %d, Message Trace Level: %d\n",
  609.           DebugLevel, MMTrace );
  610.     if (Dimension) printf("  Dimension       : %d\n", Dimension);
  611.  
  612. #ifdef OLDEDEN
  613.     /*
  614.      * Get LNN of public pod on our diskserver.  This is LNN
  615.      * we willll use in UIDs for created ejects.  
  616.      *
  617.      * ASSUMPTIONS: 
  618.      *    1. myHostName still contains the result of the gethostname 
  619.      *       call made above.  
  620.      *    2. A diskservers entry in /etc/hosts contains an 
  621.      *       alias of form "xND" for each machine x (including 
  622.      *       itself) to which it provides disk service.
  623.      *       Each Vax is considered to be its own diskserver.
  624.      */
  625.     diskserver = (void) strcat(myHostName, "ND"); /* this clobbers myHostName! */
  626.     hp = gethostbyname( diskserver );
  627.     if ( hp == NULL ) {
  628.         printf("No host entry for %s.\n", diskserver);
  629.         exit(0);
  630.     }
  631.     defaultCS = (NodeNum) defaultLnn( hp->h_addr[3], (int) True );
  632.     printf ("  Default CS for created ejects: %d (dec)\n", defaultCS );
  633. #endif OLDEDEN
  634.  
  635. #ifndef NODISK
  636.     if(!nodisk) {
  637.       (void) sprintf(NODEDIR, "%sNodes/Em%04x", EMDIR, NodeNumber);
  638.       printf("  Node directory  : %s\n", NODEDIR);
  639.       /* Make sure the node directory exists */
  640.       if ( stat(NODEDIR, &stbuf) < 0 ) {
  641.         if ( (errno == ENOENT) && ( mkdir(NODEDIR, 0777) == 0 ) ) {
  642.           ErrMsg("No temp directory. Created %s\n",NODEDIR);
  643.         } else {
  644.           ErrMsg("Cannot create temp directory %s\n", NODEDIR);
  645.           fflush(stdout);  fflush(stderr);
  646.           perror("stat/mkdir");
  647.           exit( 1 );
  648.         }
  649.       } else {
  650.         if ( ! (stbuf.st_mode & S_IFDIR) ) {
  651.           ErrMsg("%s already exists and is not a directory.\n",NODEDIR);
  652.           exit( 1 );
  653.         }
  654.       }
  655.       DebugMsg(5, "EMDIR:    %s\n",EMDIR);
  656.       DebugMsg(5, "NODEDIR:  %s\n",NODEDIR);
  657.     }
  658. #endif NODISK
  659.  
  660. #ifndef xkernel
  661.     /*
  662.      * Define an alternate stack where ULTRIX signal handlers may 
  663.      * execute.
  664.      */
  665.     
  666.     theStackInfo.ss_sp = (caddr_t) &signalstack[SIGSTACKSIZE-2];
  667.     theStackInfo.ss_onstack = 0;
  668.     if (sigstack(&theStackInfo, NULL) == -1) {
  669.         fflush(stdout);  fflush(stderr);
  670.         perror("sigstack");
  671.         abort();
  672.     }
  673.     
  674. #endif xkernel
  675.  
  676.     /* If we are killed, shut down gracefully */
  677. #ifdef xkernel
  678.      xonfault(SigIntHandler);
  679. #else
  680.     vec.sv_handler      = SigIntHandler;
  681.     vec.sv_mask         = 0;         /* All signals enabled */
  682.     vec.sv_onstack      = 1;      /* Auxiliary stack specified */
  683.     sigvec(SIGINT, &vec, 0);   /* 0 means do not tell me old sighandler */
  684.     vec.sv_handler      = SigIntHandler;
  685.     sigvec(SIGTERM, &vec, 0);
  686.  
  687.     /* Set handler to catch NIL references in Emerald programs */
  688.     vec.sv_handler = EmBadSignal;
  689.     sigvec(SIGILL, &vec, 0); 
  690.     sigvec(SIGBUS, &vec, 0); 
  691.     sigvec(SIGSEGV, &vec, 0);
  692.  
  693.     /* Define prod handlers. */
  694.     vec.sv_handler = ProdHandler;
  695.     sigvec(SIGPROD, &vec, 0);
  696.     vec.sv_handler = DBXProdHandler;
  697.     sigvec(SIGDBXPROD, &vec, 0);
  698. #endif
  699.  
  700.     /* Initialize the task queues */
  701.     initqueue((struct Queue *) &FreeQ);
  702.     initqueue((struct Queue *) &TaskQ);
  703.     for (i = 0; i < MAXTASKQ; i++)
  704.         enqueue((struct Queue *) &FreeQ, (struct Queue *) &TaskArray[i]);
  705.  
  706.     if (!standAlone) {
  707.  
  708.     /*
  709.      * Call protocol initialization routines
  710.      */
  711.  
  712.     /* InitHOTS() also initializes the message module. */
  713.     /* Define dimension first, however.           */
  714.     lStatus = MMDefineDimension(Dimension);
  715.     if ( !mSUCCESS( lStatus ) ) {
  716.         ErrMsg("Dimension out of wack: %08x...\n",lStatus);
  717.         exit( 1 );
  718.     }
  719.     i = IsActiveNode |
  720. #if defined(vax)
  721.         IsVax
  722. #endif
  723. #if defined(sun)
  724.         IsSun
  725. #endif
  726.         ;
  727.  
  728.     {
  729.         InitHOTS(emPort);
  730.  
  731.         /* Initialize KMD */
  732.         KMDInit( htons(emPort + 1) );
  733.         /* Initialize fileload */
  734.         FLInit((unsigned short) htons(emPort + 2) );
  735.     }
  736.     }
  737.  
  738.     /*
  739.      * Install the SetFlush snapshot.
  740.      */
  741.         KMDSetSnap(SetFlush);
  742.  
  743.     BootKernel( i );
  744.  
  745. #ifndef NODISK
  746.     if (!nodisk) {
  747.       char logfile [100];
  748.       (void) sprintf (logfile, "%s/log", NODEDIR);
  749.       if ((logout = fopen (logfile, "a")) == NULL)
  750.         ErrMsg ("Cannot open log file %s\n", logfile);
  751.     }
  752.     
  753. #endif NODISK
  754.     EmInit();
  755.     /* Never return */
  756.  
  757.  
  758.     /*************************************************************/
  759.     /*   E N D   O F   I N I T I A L I Z A T I O N S             */
  760.     /*************************************************************/
  761.     }
  762. }
  763.  
  764. /*
  765.  * SigIntHandler()
  766.  *
  767.  * This routine gets called whenever the either kernel process gets
  768.  * shut down.  If we are process A, we just exit.  If we are B,
  769.  * we send a SIGINT to A and exit.
  770.  *
  771.  * Undocumented "feature" (bug?):  In 4.1bsd, the signal number is the
  772.  * first argument to the handler. In 4.2bsd, it IS documented.
  773.  *
  774.  * Try to send a shutdown message.  I don't know if this will work,
  775.  * because the task queue has been stopped, but do it anyway.
  776.  */
  777.  
  778. SigIntHandler(fSig, fCode, fContext)
  779. int                 fSig;
  780. int                 fCode;
  781. struct sigcontext  *fContext;
  782. /* For param description, see sigvec(2), ULTRIX manual                    */
  783. {
  784.     static char *sigprint[] = {
  785.         "Hangup",    "Interrupt",    "Quit",    "Illegal instruction",
  786.         "Trace trap",    "IOT",        "EMT",    "FPE",
  787.         "Kill",        "Bus error",    "Segmentation violation",
  788.         "Bad arg to sys call",    "Broken pipe",    "Alarm clock",
  789.         "Terminated",    "Em IPC",
  790.     };
  791.     char *message, buf[40];
  792. #ifndef xkernel
  793.     struct sigvec vec;
  794.     int sig;
  795. #endif
  796.  
  797.     HoldSigs(); /* Watch out for this */
  798. #ifndef xkernel
  799.     (void) fflush(stdout);(void) fflush(stderr);
  800. #endif
  801.     if (fSig > 0 && fSig <= 16)
  802.         message = sigprint[fSig - 1];
  803.     else {
  804.         (void) sprintf(buf, "Unknown signal %d", fSig);
  805.         message = buf;
  806.     }
  807.  
  808.     printf(
  809.         "**** Signal no. %d (%s) arrived -- starting termination.\n",
  810.         fSig, message);
  811.  
  812.     SendShutDownMsg(GetLNN());
  813.  
  814.     shutdownOID();
  815.  
  816. #ifndef xkernel
  817.     /*
  818.      * If this is an unexpected signal, get a core dump.
  819.      * Have to reset signals to default action first.
  820.      */
  821.     if (fSig != SIGINT && fSig != SIGTERM) {
  822.         printf( "IP = 0x%04x, Code = %d\n", fContext->sc_pc,
  823.             fCode);
  824.         vec.sv_handler = SIG_DFL;
  825.         vec.sv_mask = 0;
  826.         vec.sv_onstack = 0;
  827. #ifdef BSD
  828.         for (sig = 1; sig < NSIG; sig++)
  829.             (void) sigvec(sig, &vec, 0);
  830.         printf( "Core dumped\n");
  831.         (void) sigsetmask(0);
  832.                 if (fSig == SIGQUIT)  {
  833.                     int *dummy = (int *) -1;
  834.             *dummy = 0;
  835.         }
  836. #endif
  837.                 return; /* and UNIX will do the right thing */
  838.     }
  839. #endif
  840.     printf( "Termination done -- exiting.\n");
  841.     exit(0); /* For some unknown reason, exit(0) can cause
  842.              a segmentation fault in _fwalk */
  843. }
  844.  
  845. /* 
  846.  * ProdHandler()
  847.  *
  848.  * Can be called by sending the process an interrupt.
  849.  * The idea is to be able to 'prod' a stalled process and possibly learn
  850.  * why it stalled.
  851.  * WARNING: This procedure may be called anytime - the signal for it
  852.  * must never be held - and therefore it cannot rely on a consistent state
  853.  * of the data structures of the kernel.
  854.  */
  855. int ProdHandler()
  856. {
  857.   int i;
  858.  
  859. #ifdef xsimul
  860.   printf( "\nProd of %s%04x (pid = %d)\n", "EmeraldNode", GetLNN(), getpid());
  861. #else
  862.   printf( "\nProd of %s%04x\n", "EmeraldNode", GetLNN());
  863. #endif
  864.   printf( "SigsHeld                = %2d\n", SigsHeld);
  865.   printf( "shouldPause             = %s\n", 
  866.      shouldPause == reallyPause ? "reallyPause" : "dontPause");
  867.   printf( "Pending                 = %2d\n", Pending);
  868.   printf( "ActCount                = %2d\n", ActCount);
  869.   printf( "Status of held signals:\n");
  870.   printf( "Seq. no.   Signal no.    Count\n");
  871.   for (i=0; i < ActCount; i++) {
  872.     printf( " %4d        %4d        %4d\n",
  873.        i,    ActSig[i],  SigTable[ActSig[i]].Ntimes);
  874.   }
  875.   printf( "CurrentSSP 0x%08x", currentSSP);
  876.   if (NonNULL(currentSSP)) {
  877.     printf( "  processOID 0x%08x", currentSSP->processOID);
  878.   }
  879.   printf( "\n*** End Prod ***\n");
  880. }
  881.  
  882. /* Does nothing on a kill -30; can be used to get dbx attention
  883.  * by setting a break point here, e.g., stop in DBXProdHandler
  884.  */
  885. int DBXProdHandler()
  886. {
  887. }
  888.